package com.example.tianling.WebSocket.handler;

import com.alibaba.fastjson.JSONObject;
import com.example.tianling.baiduAi.BaiduAi;
import com.example.tianling.common.componment.XfXhStreamClient;
import com.example.tianling.common.listener.XfXhWebSocketListener;
import com.example.tianling.common.utils.RTCUtils;
import com.example.tianling.common.vo.RoomVo;
import com.example.tianling.common.utils.RedisUtils;
import com.example.tianling.common.utils.WsMessage;
import com.example.tianling.config.XfXhConfig;
import com.example.tianling.dto.MsgDTO;
import com.example.tianling.entity.*;
import com.example.tianling.service.Impl.*;
import com.example.tianling.service.MatchService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import okhttp3.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

@Component
public class TrainWebSocketHandler implements WebSocketHandler{
    private static final Logger logger = LoggerFactory.getLogger(TrainWebSocketHandler.class);
    private static final Gson gson = new GsonBuilder().create();
    private static UserServiceImpl userService;
    private static RoomServiceImpl roomService;
    private static BookServiceImpl bookService;
    private static RedisUtils redisUtils;
    private static MatchService matchService;
    private static TrainResultServiceImpl trainResultService;
    private static XfXhStreamClient xfXhStreamClient;
    private static XfXhConfig xfXhConfig;
    private static RTCUtils RTCUtils;
    private static BaiduAi baiduAi;

    // 房间信息
    private static final Map<String, RoomEntity> roomInfo = new HashMap<>();
    private static final Map<String, List<RoomUserEntity>> roomUser = new HashMap<>();
    private static final Map<String, BookEntity> book = new HashMap<>();
    private static final Map<String, String> recordTask = new HashMap<>();


    // 房间进行时相关
    private static final Map<String, Boolean> isStart = new HashMap<>();
    private static final Map<String, Map<String, Integer>> userOrder = new HashMap<>();
    private static final Map<String, Integer> speakNum = new HashMap<>();
    private static final Map<String, Integer> agreeNum = new HashMap<>();

    private static final Map<String, Boolean> isChooseBook = new HashMap<>();
    private static final Map<String, Boolean> isEndRead = new HashMap<>();
    private static final Map<String, Map<String, Boolean>> isPersonalEnd = new HashMap<>();
    private static final Map<String, Boolean> isDiscussionEnd = new HashMap<>();
    private static final Map<String, Boolean> isApply = new HashMap<>();
    private static final Map<String, Map<String, Boolean>> isSummaryEnd = new HashMap<>();

    // 训练结果
    private static final Map<String, Integer> resultNum = new HashMap<>();
    private static final Map<String, Map<String, Integer>> personalTime = new HashMap<>();
    private static final Map<String, Map<String, Integer>> discussionNum = new HashMap<>();
    private static final Map<String, Map<String, Integer>> summaryTime = new HashMap<>();
    private static final Map<String, Map<String, String>> startTime = new HashMap<>();
    private static final Map<String, Map<String, String>> startType = new HashMap<>();
    private static final Map<String, Map<String, String>> personal = new HashMap<>();
    private static final Map<String, Map<String, String>> personalAi = new HashMap<>();

    // 保存session
    private static final Map<String, WebSocketSession> userRegistry = new ConcurrentHashMap<>();
    private static final Map<String, Set<WebSocketSession>> roomRegistry = new ConcurrentHashMap<>();

    /*
     * 进入房间
     * 1.房间不存在
     *    a.创建房间，并添加session
     *    b.添加房主: roomVo和数据表room中的房主userId
     * 2.房间存在
     *    a.用户第一次进入房间
     *       1).增加roomVo的roomUser和realNumber
     *       2).增加数据表room的realNumber和roomUser中的用户
     *    b.用户重连
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String userId = (String) session.getAttributes().get("userId");
        String roomId = (String) session.getAttributes().get("roomId");

        logger.info("用户{} 进入房间{}", userId, roomId);

        logger.info(userRegistry.toString());

        AtomicBoolean isReconnect = new AtomicBoolean(false);

        // 1.房间不存在
        if (!roomRegistry.containsKey(roomId)) {
            // a.创建房间，并添加session
            userRegistry.put(userId, session);
            Set<WebSocketSession> set = new HashSet<>();
            set.add(session);
            roomRegistry.put(roomId, set);

            // b.添加房主: roomVo和数据表room中的房主userId
            RoomEntity roomEntity = roomService.getRoom(Integer.parseInt(roomId));
            roomEntity.setUserId(Integer.parseInt(userId));
            roomInfo.put(roomId,roomEntity);

            List<RoomUserEntity> list = new ArrayList<>();
            roomUser.put(roomId, list);
        } else {
            userRegistry.put(userId, session);
            roomRegistry.get(roomId).add(session);

        }
        logger.info(userRegistry.toString());

        roomUser.get(roomId).forEach(
                x -> {
                    if (userId.equals(x.getUserId().toString())) {
                        isReconnect.set(true);}
                }
        );
        RoomUserEntity roomUserEntity = createRoomUser(roomId, userId);
        if (!isReconnect.get()) {
            logger.info("用户{}成功进入", userId);
            roomInfo.get(roomId).setRealNumber(roomInfo.get(roomId).getRealNumber() + 1);
            roomUser.get(roomId).add(roomUserEntity);

            // 发送rtcToken
            String rtcToken = RTCUtils.getToken(roomId, Long.parseLong(userId), 3*30*30);
            Map<String, String> rtcTokenMap = new HashMap<>();
            rtcTokenMap.put("rtcToken", rtcToken);
            WsMessage<Object> rtcTokenMessage = new WsMessage<>("rtcToken", rtcTokenMap);
            sendMessageToOne(userId, rtcTokenMessage);
        }
        // 发送信息
        Map<String, Object> registerMap = new HashMap<>();
        registerMap.put("roomInfo", roomInfo.get(roomId));
        registerMap.put("roomUsers", roomUser.get(roomId));

        WsMessage<Object> registerMessage = new WsMessage<>("register", registerMap);
        sendMessageToAll(roomId, registerMessage);
        sendSystemMessage(roomId, roomUserEntity.getUserName()+"进入房间");

        logger.info(roomInfo.get(roomId).toString());
        logger.info(roomUser.get(roomId).toString());
    }


    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        // 获取session中的roomId
        String userId = (String) session.getAttributes().get("userId");
        String roomId = (String) session.getAttributes().get("roomId");

        // 获取message中的发送用户from、接收用户target、信息类型type
        JsonObject json = gson.fromJson((String) message.getPayload(), JsonObject.class);   // json解析message
        String type = json.get("type").getAsString();

        logger.info("用户 {} {}", userId, type);

        UserEntity user = userService.getUserByUserId(Integer.parseInt(userId));

        switch (type)
        {
            case "ping":
                WsMessage<Object> pong = new WsMessage<>("pong");
                sendMessageToOne(userId, pong);
                break;
            case "logout":

                if (roomInfo.get(roomId).getRoomState() == 0) {
                    Integer realNumber = roomInfo.get(roomId).getRealNumber();
                    roomInfo.get(roomId).setRealNumber(realNumber - 1);
                    roomUser.get(roomId).removeIf(x -> userId.equals(x.getUserId().toString()));

                    // c.房间还在匹配中，则减少match_type的realNumber
                    MatchEntity match = redisUtils.get("match_" + roomInfo.get(roomId).getType(), MatchEntity.class);
                    if (match != null && roomId.equals(match.getRoomId().toString())) {
                        match.setRealNumber(roomInfo.get(roomId).getRealNumber());
                        redisUtils.set("match_" + roomInfo.get(roomId).getType(), match, 3 * 60 * 60);
                    } else {
                        // d.房间不在匹配，则减少train_match表中的realNumber
                        matchService.updateRealNumber(Integer.parseInt(roomId), roomInfo.get(roomId).getRealNumber());
                    }

                    // e.如果realNumber == 0，删除roomVo,room,train_match
                    if (roomInfo.get(roomId).getRealNumber() == 0) {
                        roomService.removeRoom(Integer.parseInt(roomId));
                        matchService.removeByRoomId(Integer.parseInt(roomId));
                        // 1)房间还在匹配中,更新match_type
                        if (match != null && roomId.equals(match.getRoomId().toString())) {
                            MatchEntity newMatch = matchService.getMatch(roomInfo.get(roomId).getType());
                            redisUtils.set("match_" + roomInfo.get(roomId).getType(), newMatch, 3 * 60 * 60);
                        }
                    }

                    // 3.向房间所有用户发送logout信息
                    Map<String, Object> logoutMap = new HashMap<>();
                    logoutMap.put("roomInfo", roomInfo.get(roomId));
                    logoutMap.put("roomUsers", roomUser.get(roomId));

                    WsMessage<Object> logoutMessage = new WsMessage<>(type, logoutMap);
                    sendMessageToAll(roomId, logoutMessage);
                    sendSystemMessage(roomId, user.getUserName()+"退出房间");

                } else if (roomInfo.get(roomId).getRoomState() == 2) {
                    Integer realNumber = roomInfo.get(roomId).getRealNumber();
                    roomInfo.get(roomId).setRealNumber(realNumber - 1);
                    roomUser.get(roomId).removeIf(x -> userId.equals(x.getUserId().toString()));

                    // 3.向房间所有用户发送logout信息
                    Map<String, Object> logoutMap = new HashMap<>();
                    logoutMap.put("roomInfo", roomInfo.get(roomId));
                    logoutMap.put("roomUsers", roomUser.get(roomId));

                    WsMessage<Object> logoutMessage = new WsMessage<>(type, logoutMap);
                    sendMessageToAll(roomId, logoutMessage);
                    sendSystemMessage(roomId, user.getUserName()+"退出房间");
                }

                if (roomInfo.get(roomId).getRealNumber() == 0) { clear(roomId); }

                break;

            case "change":
                Integer targetUserId = json.get("target").getAsInt();
                RoomUserEntity targetRoomUser = null;
                for (RoomUserEntity roomUserEntity : roomUser.get(roomId)) {
                    if (targetUserId.equals(roomUserEntity.getUserId())) {
                        targetRoomUser = roomUserEntity;
                    }
                }
                if (targetRoomUser == null) {
                    WsMessage<Object> changeFailMessage = new WsMessage<>("changeFail");
                    sendMessageToAll(roomId, changeFailMessage);
                } else {
                    roomInfo.get(roomId).setUserId(targetUserId);

                    Map<String, Object> changeMap = new HashMap<>();
                    changeMap.put("roomInfo", roomInfo.get(roomId));

                    WsMessage<Object> changeMessage = new WsMessage<>(type, changeMap);
                    sendMessageToAll(roomId, changeMessage);
                    sendSystemMessage(roomId, targetRoomUser.getUserName()+"成为房主");

                }
                break;
            case "kick":
                String target = json.get("target").getAsString();

                // 1.更新roomVo: realNumber-1,删除roomUser
                roomInfo.get(roomId).setRealNumber(roomInfo.get(roomId).getRealNumber() - 1);
                UserEntity targetUser = userService.getUserByUserId(Integer.parseInt(target));

                roomUser.get(roomId).removeIf(x -> target.equals(x.getUserId().toString()));

                // 3.向房间所有用户发送logout信息
                Map<String, Object> kickMap = new HashMap<>();
                kickMap.put("roomInfo", roomInfo.get(roomId));
                kickMap.put("roomUsers", roomUser.get(roomId));

                WsMessage<Object> kickMessage = new WsMessage<>(type, kickMap);
                sendMessageToAll(roomId, kickMessage);
                sendSystemMessage(roomId, targetUser.getUserName()+"被踢出房间");

                // c.房间还在匹配中，则减少match_type的realNumber
                MatchEntity match = redisUtils.get("match_" + roomInfo.get(roomId).getType(), MatchEntity.class);
                if (match != null && roomId.equals(match.getRoomId().toString())) {
                    match.setRealNumber(roomInfo.get(roomId).getRealNumber());
                    redisUtils.set("match_" + roomInfo.get(roomId).getType(), match, 3 * 60 * 60);
                } else {
                    // d.房间不在匹配，则减少train_match表中的realNumber
                    matchService.updateRealNumber(Integer.parseInt(roomId), roomInfo.get(roomId).getRealNumber());
                }

                break;
            case "chat":
                Map<String, Object> map = new HashMap<>();
                map.put("userId", user.getUserId());
                map.put("userName", user.getUserName());
                map.put("userImg", user.getUserImg());
                map.put("content", json.get("data").getAsString());

                WsMessage<Object> chatMessage = new WsMessage<>(type, map);
                sendMessageToAll(roomId, chatMessage);
                break;
            case "ready":
                roomUser.get(roomId).forEach(
                        x -> {
                            if (userId.equals(x.getUserId().toString())) { x.setUserState(1); }
                        }
                );

                Map<String, Object> readyMap = new HashMap<>();
                readyMap.put("roomInfo", roomInfo.get(roomId));
                readyMap.put("roomUsers", roomUser.get(roomId));

                WsMessage<Object> readyMessage = new WsMessage<>(type, readyMap);
                sendMessageToAll(roomId, readyMessage);
                sendSystemMessage(roomId, user.getUserName()+"准备好了");

                break;
            case "noReady":
                roomUser.get(roomId).forEach(
                        x -> {
                            if (userId.equals(x.getUserId().toString())) { x.setUserState(0); }
                        }
                );

                Map<String, Object> noReadyMap = new HashMap<>();
                noReadyMap.put("roomInfo", roomInfo.get(roomId));
                noReadyMap.put("roomUsers", roomUser.get(roomId));

                WsMessage<Object> noReadyMessage = new WsMessage<>(type, noReadyMap);
                sendMessageToAll(roomId, noReadyMessage);
                sendSystemMessage(roomId, user.getUserName()+"取消准备了");

                break;

            case "start":
                // 1.检查房间内用户是否全部都准备：从redis取room检查
                boolean isAllReady = true;
                for (RoomUserEntity roomUserEntity : roomUser.get(roomId)) {
                    if (roomUserEntity.getUserState() == 0) {
                        isAllReady = false;
                        break;
                    }
                }

                // 2.全部准备
                if (isAllReady) {
                    initial(roomId);

                    // 修改roomState
                    roomInfo.get(roomId).setRoomState(1);
                    roomInfo.get(roomId).setIsMatch(0);
                    book.put(roomId, bookService.getDefaultBook(roomInfo.get(roomId).getType(), roomInfo.get(roomId).getArea()));

                    // 打乱用户
                    List<RoomUserEntity> list = roomUser.get(roomId);
                    Collections.shuffle(list);
                    roomUser.put(roomId, list);

                    // 发送信息
                    Map<String, Object> startSuccessMap = new HashMap<>();
                    startSuccessMap.put("roomInfo", roomInfo.get(roomId));
                    startSuccessMap.put("roomUsers", roomUser.get(roomId));
                    startSuccessMap.put("book", book.get(roomId));

                    WsMessage<Object> startSuccessMessage = new WsMessage<>("startSuccess", startSuccessMap);
                    sendMessageToAll(roomId, startSuccessMessage);
                    sendSystemMessage(roomId, "开始训练！！！");

                    startRoom(roomId);

                } else {    // 未全部准备则发送 startFail
                    WsMessage<Object> startFailMessage = new WsMessage<>("startFail");
                    sendMessageToAll(roomId, startFailMessage);
                    sendSystemMessage(roomId, "开始训练失败，请所有组员尽快准备！！！");
                }
                break;
            case "startSuccess":
                if (!isStart.get(roomId)) {
                    isStart.put(roomId, true);
//                    String channelId = json.get("channelId").getAsString();
//                    logger.info("房间{}的channelId为{}",roomId, channelId);
                    String taskId = RTCUtils.startCloudRecord(roomId);
                    recordTask.put(roomId, taskId);
                    logger.info("房间{}的录制任务的Id为{}", roomId, taskId);
                }
                break;
            case "endChooseBook":
                if (!isChooseBook.get(roomId)) {
                    isChooseBook.put(roomId, true);

                    sendSystemMessage(roomId, "选题阶段结束");
                    sendSystemMessage(roomId, "开始阅读思考阶段");

                    Integer bookId = json.get("bookId").getAsInt();
                    roomService.updateBookId(Integer.parseInt(roomId), bookId);
                    BookEntity book = bookService.getBookByBookId(bookId);

                    WsMessage<BookEntity> startReadMessage = new WsMessage<>("startRead", book);
                    sendMessageToAll(roomId, startReadMessage);
                }
                break;

            case "endRead":
                if (!isEndRead.get(roomId)) {
                    isEndRead.put(roomId, true);

                    sendSystemMessage(roomId, "选题阶段结束");
                    sendSystemMessage(roomId, "开始阅读思考阶段");
                    sendStartPersonalMessage(roomId);
                }
                break;

            case "endPersonal":
                String personalSpeaker = json.get("speakUserId").getAsString();

                if (!isPersonalEnd.get(roomId).get(personalSpeaker)) {
                    isPersonalEnd.get(roomId).put(personalSpeaker, true);

                    // 继续个人陈述
                    if (speakNum.get(roomId) < roomInfo.get(roomId).getRealNumber()) {
                        sendStartPersonalMessage(roomId);
                    } else {
                        sendSystemMessage(roomId, "个人陈述阶段结束");
                        sendSystemMessage(roomId, "自由讨论阶段开始");
                        WsMessage endAllPersonal = new WsMessage("endAllPersonal");
                        sendMessageToAll(roomId, endAllPersonal);
                    }

                }
                break;

            case "applyEndDiscussion":
                if (!isApply.get(roomId)) {
                    isApply.put(roomId, true);
                    agreeNum.put(roomId, 0);

                    sendSystemMessage(roomId, userOrder.get(roomId).get(userId)+"号考生申请结束自由讨论");
                    WsMessage applyEndDiscussionMessage = new WsMessage<>("applyEndDiscussion");
                    sendMessageToAll(roomId, applyEndDiscussionMessage);
                }
                break;

            case "disagreeEndDiscussion":
                isApply.put(roomId, false);
                sendSystemMessage(roomId, userOrder.get(roomId).get(userId)+"号考生不同意结束自由讨论");
                WsMessage disagreeMessage = new WsMessage<>("disagreeEndDiscussion");
                sendMessageToAll(roomId, disagreeMessage);
                break;

            case "agreeEndDiscussion":
                sendSystemMessage(roomId, userOrder.get(roomId).get(userId)+"号考生同意结束自由讨论");

                agreeNum.put(roomId, agreeNum.get(roomId) + 1);
                if (agreeNum.get(roomId).equals(roomInfo.get(roomId).getRealNumber())) {
                    isDiscussionEnd.put(roomId, true);

                    sendSystemMessage(roomId, "自由讨论阶段结束");
                    sendSystemMessage(roomId, "总结陈词阶段开始");

                    WsMessage<Object> endDiscussionMessage = new WsMessage<>("endDiscussion");
                    sendMessageToAll(roomId, endDiscussionMessage);
                    sendStartSummaryMessage(roomId);
                } else {
                    Map<String, Object> agreeMap = new HashMap<>();
                    agreeMap.put("agreeNum", agreeNum.get(roomId));
                    WsMessage<Object> agreeMessage = new WsMessage<>(type, agreeMap);
                    sendMessageToAll(roomId, agreeMessage);
                }
                break;

            case "endDiscussion":
                if (!isDiscussionEnd.get(roomId)) {
                    isDiscussionEnd.put(roomId, true);

                    sendSystemMessage(roomId, "自由讨论阶段结束");
                    sendSystemMessage(roomId, "总结陈词阶段开始");

                    WsMessage<Object> endDiscussionMessage = new WsMessage<>("endDiscussion");
                    sendMessageToAll(roomId, endDiscussionMessage);
                    sendStartSummaryMessage(roomId);
                }
                break;

            case "endSummary":
                String summarySpeaker = json.get("speakUserId").getAsString();
                if (!isSummaryEnd.get(roomId).get(summarySpeaker)) {
                    isSummaryEnd.get(roomId).put(summarySpeaker, true);
                    speakNum.put(roomId, speakNum.get(roomId) - 1);

                    if (speakNum.get(roomId) > 0) {
                        sendStartSummaryMessage(roomId);
                    } else {
                        RTCUtils.stopCloudRecord(roomId, recordTask.get(roomId));
                        roomInfo.get(roomId).setRoomState(2);
                        WsMessage endAllSummary = new WsMessage("endAllSummary");
                        sendSystemMessage(roomId, "总结陈述阶段结束");
                        sendMessageToAll(roomId, endAllSummary);
                    }
                }
                break;

            case "destory":
                WsMessage destoryMessage = new WsMessage<>(type);
                sendMessageToAll(roomId, destoryMessage);

                // 2.将rooms中room删掉
                roomRegistry.remove(roomId);
                clear(roomId);
                break;

            case "personal":
                if (json.get("personal") != null) {
                    String personalText = json.get("personal").getAsString();
                    String personalAiText = getAiAnswer(roomId, personalText);

                    personal.get(roomId).put(userId, personalText);
                    personalAi.get(roomId).put(userId, personalAiText);
                }

                break;

            case "result":
                resultNum.put(roomId,resultNum.get(roomId) + 1);

                personalTime.get(roomId).put(userId, json.get("personalTime").getAsInt());
                discussionNum.get(roomId).put(userId, json.get("discussionNum").getAsInt());
                summaryTime.get(roomId).put(userId, json.get("summaryTime").getAsInt());

                startTime.get(roomId).put(userId, json.get("startTime").getAsJsonArray().toString());
                startType.get(roomId).put(userId, json.get("startType").getAsJsonArray().toString());

                if (resultNum.get(roomId).equals(roomInfo.get(roomId).getRealNumber())) {
                    getResult(roomId);
                }
        }
    }


    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        String userId = (String) session.getAttributes().get("userId");
        logger.info("用户{}的websokcet出现错误: {}", userId, exception.toString());
        logger.info(exception.getMessage());
    }
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        String roomId = (String) session.getAttributes().get("roomId");
        String userId = (String) session.getAttributes().get("userId");

        logger.info("用户{}关闭websokcet的code: {}", userId, closeStatus.getCode());
        userRegistry.remove(userId);
        roomRegistry.get(roomId).remove(session);

        if (closeStatus.getCode() == 1006 && !roomRegistry.get(roomId).isEmpty()
                && userId.equals(roomInfo.get(roomId).getUserId().toString())) {
            // 更换房主
            String newHost = "";
            List<RoomUserEntity> roomUserList = roomUser.get(roomId);
            for (RoomUserEntity roomUserEntity : roomUserList) {
                if (!userId.equals(roomUserEntity.getUserId().toString())) {
                    newHost = roomUserEntity.getUserName();
                    roomInfo.get(roomId).setUserId(roomUserEntity.getUserId());
                    break;
                }
            }

            // 发送更换信息
            Map<String, Object> changeMap = new HashMap<>();
            changeMap.put("roomInfo", roomInfo.get(roomId));

            WsMessage<Object> changeMessage = new WsMessage<>("change", changeMap);
            sendMessageToAll(roomId, changeMessage);
            sendSystemMessage(roomId, newHost+"成为房主");
        }

        if (roomRegistry.get(roomId).isEmpty()) {
            roomRegistry.remove(roomId);
            if (roomInfo.get(roomId) != null && roomInfo.get(roomId).getRealNumber() > 0) {
                if (roomInfo.get(roomId).getRoomState() == 0) {
                    // c.房间还在匹配中，则减少match_type的realNumber
                    MatchEntity match = redisUtils.get("match_" + roomInfo.get(roomId).getType(), MatchEntity.class);
                    if (match != null && roomId.equals(match.getRoomId().toString())) {
                        match.setRealNumber(roomInfo.get(roomId).getRealNumber());
                        redisUtils.set("match_" + roomInfo.get(roomId).getType(), match, 3 * 60 * 60);
                    } else {
                        // d.房间不在匹配，则减少train_match表中的realNumber
                        matchService.updateRealNumber(Integer.parseInt(roomId), roomInfo.get(roomId).getRealNumber());
                    }
                }
                clear(roomId);
            }
        }
    }
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }


    private RoomUserEntity createRoomUser(String roomId, String userId) {
        UserEntity user = userService.getUserByUserId(Integer.parseInt(userId));
        RoomUserEntity roomUser = new RoomUserEntity();
        roomUser.setUserId(user.getUserId());
        roomUser.setUserName(user.getUserName());
        roomUser.setUserImg(user.getUserImg());
        roomUser.setUserState(0);
        roomUser.setRoomId(Integer.parseInt(roomId));
        return roomUser;
    }

    void startRoom(String roomId) {
        roomService.updateById(roomInfo.get(roomId));
        matchService.removeByRoomId(Integer.parseInt(roomId));

        MatchEntity match = redisUtils.get("match_"+roomInfo.get(roomId).getType(), MatchEntity.class);
        if (match == null || roomId.equals(match.getRoomId().toString())) {
            MatchEntity newMatch = matchService.getMatch(roomInfo.get(roomId).getType());
            redisUtils.set("match_"+roomInfo.get(roomId).getType(), newMatch, 3*60*60);
        }
    }

    private String getAiAnswer(String roomId, String personalText) throws IOException {


        String prompt = "请基于题目点评一下该考生的回答\n" +
                "1.指出该考生回答中存在的三到五个问题，并给出改善的建议。\n" +
                "2.基于题目给考生做出一些考生没有想到的思路扩展，比如新的思考角度，新的和题目相关的例子或者新的论证。要具体指出在考生回答的哪个部分可以补充进去。";
        String pre = "以下是考生回答：";
        String content  = "以下是题干："+book.get(roomId).getSummuny()+'\n';
        String jsonString = "{\"messages\":[{\"role\":\"user\",\"content\":\""+(content+pre+personalText+prompt).replaceAll("\r","").replaceAll("\n","\\\\n")+"\"}]}";
        String result = baiduAi.getBaiduAi(jsonString.toString());

        return result;
    }

    private void getResult(String roomId) {
        List<TrainResultEntity> resultList = new ArrayList<>();
        for (RoomUserEntity roomUser : roomUser.get(roomId)) {
            Integer userId = roomUser.getUserId();
            TrainResultEntity result = new TrainResultEntity();
            result.setRoomId(Integer.parseInt(roomId));
            result.setUserId(userId);
            result.setPersonalTime(personalTime.get(roomId).get(userId.toString()));
            result.setDiscussionNum(discussionNum.get(roomId).get(userId.toString()));
            result.setSummaryTime(summaryTime.get(roomId).get(userId.toString()));
            result.setStartTime(startTime.get(roomId).get(userId.toString()));
            result.setStartType(startType.get(roomId).get(userId.toString()));
            logger.info(result.getStartTime());
            logger.info(result.getStartType());
            result.setPersonal(personal.get(roomId).get(userId.toString()));
            result.setPersonalAi(personalAi.get(roomId).get(userId.toString()));
            resultList.add(result);
        }
        logger.info(resultList.toString());
        trainResultService.saveBatch(resultList);
    }

    private void sendStartPersonalMessage(String roomId) throws JsonProcessingException {
        speakNum.put(roomId, speakNum.get(roomId) + 1);

        RoomUserEntity roomUserEntity = roomUser.get(roomId).get(speakNum.get(roomId) - 1);

        Map<String, Object> startPersonalMap = new HashMap<>();
        startPersonalMap.put("speakNum", speakNum.get(roomId));
        startPersonalMap.put("speakUserId", roomUserEntity.getUserId());
        WsMessage startPersonalMessage = new WsMessage("startPersonal", startPersonalMap);

        sendSystemMessage(roomId, speakNum.get(roomId)+"号考生开始个人陈述");
        sendMessageToAll(roomId, startPersonalMessage);
    }

    private void sendStartSummaryMessage(String roomId) throws JsonProcessingException {

        RoomUserEntity roomUserEntity = roomUser.get(roomId).get(speakNum.get(roomId) - 1);

        Map<String, Object> startSummaryMap = new HashMap<>();
        startSummaryMap.put("speakNum", speakNum.get(roomId));
        startSummaryMap.put("speakUserId", roomUserEntity.getUserId());
        WsMessage startSummaryMessage = new WsMessage("startSummary", startSummaryMap);

        sendSystemMessage(roomId, speakNum.get(roomId)+"号考生开始总结陈词");
        sendMessageToAll(roomId, startSummaryMessage);
    }

    private void initial(String roomId) {

        recordTask.put(roomId, "");

        // 房间阶段变量初始化
        isChooseBook.put(roomId, false);
        isEndRead.put(roomId, false);

        // 个人陈述和总结陈述结束初始化
        isStart.put(roomId, false);
        speakNum.put(roomId, 0);
        userOrder.put(roomId, new HashMap<>());
        isPersonalEnd.put(roomId, new HashMap<>());
        isSummaryEnd.put(roomId, new HashMap<>());
        int order = 0;
        for (RoomUserEntity roomUserEntity : roomUser.get(roomId)) {
            order = order + 1;
            userOrder.get(roomId).put(roomUserEntity.getUserId().toString(), order);
            isPersonalEnd.get(roomId).put(roomUserEntity.getUserId().toString(), false);
            isSummaryEnd.get(roomId).put(roomUserEntity.getUserId().toString(), false);
        }

        // 自由阶段变量初始化
        isDiscussionEnd.put(roomId, false);
        isApply.put(roomId, false);

        // 训练结果变量初始化
        resultNum.put(roomId, 0);
        personalTime.put(roomId, new HashMap<>());
        discussionNum.put(roomId, new HashMap<>());
        summaryTime.put(roomId, new HashMap<>());
        startTime.put(roomId, new HashMap<>());
        startType.put(roomId, new HashMap<>());
        personal.put(roomId, new HashMap<>());
        personalAi.put(roomId, new HashMap<>());
        roomUser.get(roomId).forEach(
                x -> {
                    personalTime.get(roomId).put(x.getUserId().toString(), 0);
                    discussionNum.get(roomId).put(x.getUserId().toString(), 0);
                    summaryTime.get(roomId).put(x.getUserId().toString(), 0);
                    startTime.get(roomId).put(x.getUserId().toString(), "");
                    startType.get(roomId).put(x.getUserId().toString(), "");
                    personal.get(roomId).put(x.getUserId().toString(), "");
                    personalAi.get(roomId).put(x.getUserId().toString(), "");
                }
        );

    }
    void clear(String roomId) {
        roomInfo.remove(roomId);
        roomUser.remove(roomId);
        book.remove(roomId);
        recordTask.remove(roomId);

        isStart.remove(roomId);
        isChooseBook.remove(roomId);
        isEndRead.remove(roomId);
        isPersonalEnd.remove(roomId);
        isDiscussionEnd.remove(roomId);
        isApply.remove(roomId);
        isSummaryEnd.remove(roomId);

        userOrder.remove(roomId);
        speakNum.remove(roomId);
        agreeNum.remove(roomId);

        resultNum.remove(roomId);
        personalTime.remove(roomId);
        discussionNum.remove(roomId);
        summaryTime.remove(roomId);
        startTime.remove(roomId);
        startType.remove(roomId);
        personal.remove(roomId);
        personalAi.remove(roomId);
    }

    // 发送信息给房间所有用户
    public void sendMessageToAll(String roomId, WsMessage wsMessage) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        TextMessage textMessage = new TextMessage(objectMapper.writeValueAsString(wsMessage));
        roomRegistry.get(roomId).forEach(
                x->{
                    try {
                        x.sendMessage(textMessage);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
        );
    }

    public void sendMessageToOne(String userId, WsMessage wsMessage) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        TextMessage textMessage = new TextMessage(objectMapper.writeValueAsString(wsMessage));

        userRegistry.get(userId).sendMessage(textMessage);
    }
    // 发送信息给房主

    public void sendSystemMessage(String roomId, String content) throws JsonProcessingException {
        Map<String, Object> map = new HashMap<>();
        map.put("userId", -1);
        map.put("content", content);
        WsMessage message = new WsMessage("chat", map);
        sendMessageToAll(roomId, message);
    }

    public void mergeRoom(String roomId, String matchRoomId) throws JsonProcessingException {
        roomRegistry.get(matchRoomId).stream().forEach(
                x->{
                    roomRegistry.get(roomId).add(x);
                }
        );
        roomRegistry.remove(matchRoomId);

        RoomVo matchRoomVo = redisUtils.get("room_"+matchRoomId, RoomVo.class);
        List<RoomUserEntity> roomUserList = new ArrayList<>(matchRoomVo.getRoomUsers());

        RoomVo roomVo = redisUtils.get("room_"+roomId, RoomVo.class);
        for (RoomUserEntity roomUser: roomUserList) {
            roomVo.addRoomUser(roomUser);
        }
        WsMessage wsMessage = new WsMessage<>("register", roomVo);
        sendMessageToAll(roomId, wsMessage);
    }

    // setBean方法
    @Autowired
    public void setUserService(UserServiceImpl userService) {TrainWebSocketHandler.userService = userService;}

    @Autowired
    public void setRoomService(RoomServiceImpl roomService) {TrainWebSocketHandler.roomService = roomService;}
    @Autowired
    public void setBookService(BookServiceImpl bookService) { TrainWebSocketHandler.bookService = bookService;}
    @Autowired
    public void setRedisUtils(RedisUtils redisUtils) { TrainWebSocketHandler.redisUtils = redisUtils; }

    @Autowired
    public void setMatchService(MatchService matchService) { TrainWebSocketHandler.matchService = matchService; }

    @Autowired
    public void setTrainResultService(TrainResultServiceImpl trainResultService) { TrainWebSocketHandler.trainResultService = trainResultService; }

    @Resource
    public void setXfXhStreamClient(XfXhStreamClient xfXhStreamClient) { TrainWebSocketHandler.xfXhStreamClient = xfXhStreamClient; }

    @Resource
    public void setXfXhConfig(XfXhConfig xfXhConfig) { TrainWebSocketHandler.xfXhConfig = xfXhConfig; }

    @Autowired
    public void setRtcToken(RTCUtils RTCUtils) { TrainWebSocketHandler.RTCUtils = RTCUtils; }

    @Autowired
    public void setBaiduAi(BaiduAi baiduAi) { TrainWebSocketHandler.baiduAi = baiduAi; }
}
